import os
import uuid
from copy import deepcopy
from typing import *

from globalVar import GlobalVar
from utils.error import PreparationError
import datetime
import re
import yaml
from config import ROOT_DIR
from utils.strategy.loader import StrategyLoader


class ConfigType:

    def __init__(self, s_time: str, e_time: str, show_factors: List[str] = None, **kwargs):
        try:
            s_group = re.match(r'^(\d{4})[-\\/](\d{1,2})[-\\/](\d{1,2})(\s(\d\d):(\d\d):(\d\d))?$', s_time).groups()
            e_group = re.match(r'^(\d{4})[-\\/](\d{1,2})[-\\/](\d{1,2})(\s(\d\d):(\d\d):(\d\d))?$', e_time).groups()
        except AttributeError:
            raise PreparationError(f'错误的时间格式')
        if s_group[3] is None:
            self.s_time = datetime.datetime(int(s_group[0]), int(s_group[1]), int(s_group[2]),
                                            tzinfo=datetime.timezone.utc)
        else:
            self.s_time = datetime.datetime(int(s_group[0]), int(s_group[1]), int(s_group[2]), int(s_group[4]),
                                            int(s_group[5]), int(s_group[6]), tzinfo=datetime.timezone.utc)
        if e_group[3] is None:
            self.e_time = datetime.datetime(int(e_group[0]), int(e_group[1]), int(e_group[2]),
                                            tzinfo=datetime.timezone.utc)
        else:
            self.e_time = datetime.datetime(int(e_group[0]), int(e_group[1]), int(e_group[2]), int(e_group[4]),
                                            int(e_group[5]), int(e_group[6]), tzinfo=datetime.timezone.utc)
        self._attr: Dict[str, Any] = kwargs
        # 需要展示的因子值
        self.show_factors: List[str] = show_factors

    def inject(self, exe) -> None:
        """
        将配置注入执行器
        :param exe: 执行器
        :return:
        """
        arg_id = f'{self.s_time.strftime("%y%m%d")}-{self.e_time.strftime("%y%m%d")}' + '_'.join(
            ['%s{%s}' % (k, v) for k, v in self._attr.items()])
        exe.strategy.arg_id = (exe.strategy_name + '-' + arg_id) if arg_id and exe.async_type else exe.strategy_name
        for k, v in self._attr.items():
            exe.strategy.system_conf[k] = deepcopy(v)

    def copy(self, **kwargs) -> 'ConfigType':
        """
        复制配置并修改参数
        :param kwargs:
        :return:
        """
        new = deepcopy(self)
        new._attr.update(kwargs)
        return new

    def __setitem__(self, key: str, value: Any):
        self._attr[key] = value

    def __getitem__(self, key: str) -> Any:
        return self._attr[key]

    def __str__(self):
        if len(self._attr) == 0:
            return ''
        return self._attr.__str__()


class ActualConfigType(ConfigType):
    def __init__(self, account: str,
                 s_time: str = None, e_time: str = None, cron_option: Mapping[str, str] = None, **kwargs):
        s_time = '1900-1-1' if s_time is None else s_time
        e_time = '2100-1-1' if e_time is None else e_time
        try:
            with open(os.path.join(ROOT_DIR, 'account.yaml'), 'r', encoding='utf-8') as f:
                data: Dict[str, Any] = yaml.safe_load(f)
            self.api_key = data['accounts'][account]['apiKey']
            self.secret_key = data['accounts'][account]['secretKey']
        except Exception as e:
            raise PreparationError(f'读取账户配置失败{e.__str__()}')
        super().__init__(s_time, e_time, **kwargs)
        self.cron_option = cron_option
        self.account_name: str = account

